{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# How to add a custom system prompt to the prebuilt ReAct agent\n",
    "\n",
    "This tutorial will show how to add a custom system prompt to the prebuilt ReAct agent. Please see [this tutorial](./create-react-agent.ipynb) for how to get started with the prebuilt ReAct agent\n",
    "\n",
    "You can add a custom system prompt by passing a string to the `stateModifier` param.\n",
    "\n",
    "<div class=\"admonition tip\">\n",
    "    <p class=\"admonition-title\">Compatibility</p>\n",
    "    <p>\n",
    "        The <a href=\"https://langchain-ai.github.io/langgraphjs/reference/types/langgraph_prebuilt.CreateReactAgentParams.html\"><code>stateModifier</code></a> parameter was added in <code>@langchain/langgraph>=0.2.27</code>.\n",
    "        <br />\n",
    "        If you are on an older version, you will need to use the deprecated <code>messageModifier</code> parameter.\n",
    "        <br />\n",
    "        For help upgrading, see <a href=\"/langgraphjs/how-tos/manage-ecosystem-dependencies/\">this guide</a>.\n",
    "    </p>\n",
    "</div>\n",
    "\n",
    "## Setup\n",
    "\n",
    "First, we need to install the required packages.\n",
    "\n",
    "```bash\n",
    "yarn add @langchain/langgraph @langchain/openai @langchain/core\n",
    "```\n",
    "\n",
    "This guide will use OpenAI's GPT-4o model. We will optionally set our API key\n",
    "for [LangSmith tracing](https://smith.langchain.com/), which will give us\n",
    "best-in-class observability."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ReAct Agent with system prompt: LangGraphJS\n"
     ]
    }
   ],
   "source": [
    "// process.env.OPENAI_API_KEY = \"sk_...\";\n",
    "\n",
    "// Optional, add tracing in LangSmith\n",
    "// process.env.LANGCHAIN_API_KEY = \"ls__...\"\n",
    "// process.env.LANGCHAIN_CALLBACKS_BACKGROUND = \"true\";\n",
    "process.env.LANGCHAIN_CALLBACKS_BACKGROUND = \"true\";\n",
    "process.env.LANGCHAIN_TRACING_V2 = \"true\";\n",
    "process.env.LANGCHAIN_PROJECT = \"ReAct Agent with system prompt: LangGraphJS\";"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Code\n",
    "\n",
    "Now we can use the prebuilt `createReactAgent` function to setup our agent with a system prompt:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import { ChatOpenAI } from \"@langchain/openai\";\n",
    "import { tool } from '@langchain/core/tools';\n",
    "import { z } from 'zod';\n",
    "import { createReactAgent } from \"@langchain/langgraph/prebuilt\";\n",
    "\n",
    "const model = new ChatOpenAI({\n",
    "    model: \"gpt-4o\",\n",
    "  });\n",
    "\n",
    "const getWeather = tool((input) => {\n",
    "    if (input.location === 'sf') {\n",
    "        return 'It\\'s always sunny in sf';\n",
    "    } else {\n",
    "        return 'It might be cloudy in nyc';\n",
    "    }\n",
    "}, {\n",
    "    name: 'get_weather',\n",
    "    description: 'Call to get the current weather.',\n",
    "    schema: z.object({\n",
    "        location: z.enum(['sf','nyc']).describe(\"Location to get the weather for.\"),\n",
    "    })\n",
    "})\n",
    "\n",
    "// We can add our system prompt here\n",
    "const prompt = \"Respond in Italian\"\n",
    "\n",
    "const agent = createReactAgent({ llm: model, tools: [getWeather], stateModifier: prompt });"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Usage\n",
    "\n",
    "Let's verify that the agent does indeed respond in Italian!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "what is the weather in NYC?\n",
      "-----\n",
      "\n",
      "[\n",
      "  {\n",
      "    name: 'get_weather',\n",
      "    args: { location: 'nyc' },\n",
      "    type: 'tool_call',\n",
      "    id: 'call_PqmKDQrefHQLmGsZSSr4C7Fc'\n",
      "  }\n",
      "]\n",
      "-----\n",
      "\n",
      "It might be cloudy in nyc\n",
      "-----\n",
      "\n",
      "A New York potrebbe essere nuvoloso. Hai altre domande o posso aiutarti in qualcos'altro?\n",
      "-----\n",
      "\n"
     ]
    }
   ],
   "source": [
    "let inputs = { messages: [{ role: \"user\", content: \"what is the weather in NYC?\" }] };\n",
    "let stream = await agent.stream(inputs, {\n",
    "  streamMode: \"values\",\n",
    "});\n",
    "\n",
    "for await (\n",
    "  const { messages } of stream\n",
    ") {\n",
    "  let msg = messages[messages?.length - 1];\n",
    "  if (msg?.content) {\n",
    "    console.log(msg.content);\n",
    "  } else if (msg?.tool_calls?.length > 0) {\n",
    "    console.log(msg.tool_calls);\n",
    "  } else {\n",
    "    console.log(msg);\n",
    "  }\n",
    "  console.log(\"-----\\n\");\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "TypeScript",
   "language": "typescript",
   "name": "tslab"
  },
  "language_info": {
   "codemirror_mode": {
    "mode": "typescript",
    "name": "javascript",
    "typescript": true
   },
   "file_extension": ".ts",
   "mimetype": "text/typescript",
   "name": "typescript",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
